﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

using ProjectBase.Core;
using ProjectBase.Core.Tools.Export;

namespace ProjectBase.Tools.Export.Word
{
    public class WordExporter : IWordExporter
    {
        public virtual bool Execute(IWordExporterData model)
        {
            Model = model;

            return LoadTemplate()
                && ProcessDocument()
                && FlushDocument();
        }

        #region protected
        protected virtual bool LoadTemplate()
        {
            if (Model.Entity.IsNull()
                || Model.DataSource.IsEmpty())
            {
                this.PublishError(Constants.Messages.NullValueWasProvided1
                    , "DataSource");
                return false;
            }

            try
            {
                Stream = new MemoryStream();
                Stream.Write(Model.DataSource, 0, Model.DataSource.Length);

                return true;
            }
            catch (Exception ex)
            {
                this.PublishFatal(ex);
            }
            return false;
        }
        protected virtual bool ProcessDocument()
        {
            try
            {
                using (var package = WordprocessingDocument.Open(Stream, true))
                {
                    var body = package.MainDocumentPart.Document.Body;

                    var parts = Parse(body);

                    Walk(parts, Model.Entity);
                }
                return true;
            }
            catch (Exception ex)
            {
                this.PublishFatal(ex);
                return false;
            }
        }
        protected virtual bool FlushDocument()
        {
            try
            {
                var buffer = new byte[Stream.Length];

                Stream.Position = 0;
                Stream.Read(buffer, 0, buffer.Length);

                Model.OutputData = buffer;
                return true;
            }
            catch (Exception ex)
            {
                this.PublishFatal(ex);
                return false;
            }
        }
        #endregion protected

        #region properties
        protected virtual IWordExporterData Model { get; set; }
        protected virtual Stream Stream { get; set; }
        #endregion properties

        #region Parse & Walk

        protected virtual IEnumerable<DocPart> Parse(Body body)
        {
            return new DocumentParser().Execute(body);
        }

        protected virtual void Walk<TPersistent>(IEnumerable<DocPart> parts, TPersistent entity)
            where TPersistent : class, IPersistentObject
        {
            new DocumentWalker().Execute(parts, entity);
        }

        #endregion Parse & Walk
    }
}